package game;

import game.Card.Value;

import java.util.*;

public class HandEvaluator {
	public static Card.Value checkForRoyalFlush(ArrayList<Card> cards){
		if (checkForStraightFlush(cards) == Card.Value.ACE){
			return Card.Value.ACE;
		}
		return null;
	}

	public static Card.Value checkForStraightFlush(ArrayList<Card> cards) {
		if (checkForFlush(cards) != null){
			ArrayList<Card> flush = greatestChanceAtFlush(cards);
			return checkForStraight(flush);
		}
		return null;
	}

	public static Value checkForStraight(ArrayList<Card> cards) {
		if (cards.size() >= 5){
			for (int i = 2; i < 15; i++){
				boolean works = true;
				for (int j = 0;j < 5 ;j++){
					if (!contains(cards,Value.cardWithInt(i + j))){
						works = false;
					}
				}
				if (works){
					return Value.cardWithInt(i + 4);
				}
			}
			boolean works = contains(cards,Value.cardWithInt(14));
			for (int j = 2;j < 6 ;j++){
				if (!contains(cards,Value.cardWithInt(j))){
					works = false;
				}
			}
			if (works){
				return Value.cardWithInt(5);
			}
		}
		return null;
	}

	private static boolean contains(ArrayList<Card> cards, Value cardWithInt) {
		for (int i = 0; i < cards.size(); i++){
			if (cards.get(i).getValue() == cardWithInt){
				return true;
			}
		}
		return false;
	}

	public static ArrayList<Card> greatestChanceAtFlush(ArrayList<Card> cards) {
		ArrayList<Card> winningArray = new ArrayList<Card>();
		for (Card.Suit s: Card.Suit.values()){
			ArrayList<Card> temp = new ArrayList<Card>();
			for (Card c: cards){
				if (c.getSuit() == s){
					temp.add(c);
				}
			}
			if (temp.size() > winningArray.size()){
				winningArray = temp;
			}
		}
		return winningArray;
	}

	public static Card.Value checkForFlush(ArrayList<Card> cards) {
		ArrayList<Card> flush = greatestChanceAtFlush(cards);
		if (flush.size() >= 5){
			return highestCard(cards);
		}
		return null;
	}

	public static Value highestCard(ArrayList<Card> cards) {
		Value highest = cards.get(0).getValue();
		for (int i = 1; i < cards.size(); i++){
			if (cards.get(i).getValue().value() > highest.value()){
				highest = cards.get(i).getValue();
			}
		}
		return highest;
	}

	public static Value checkForFourOfAKind(ArrayList<Card> cards) {
		for (int i = 14; i > 1; i--){
			int numCounter = 0;
			for (Card c: cards){
				if (c.getValue() == Value.cardWithInt(i)){
					numCounter++;
				}
			}
			if (numCounter == 4){
				return Value.cardWithInt(i);
			}
		}
		return null;
	}

	public static Value checkForFullHouse(ArrayList<Card> cards) {
		ArrayList<Card> threeKind = cardsForThreeKind(cards);
		if (threeKind != null){
			ArrayList<Card> remaining = new ArrayList<Card>();
			for (Card c: cards){
				if (!threeKind.contains(c)){
					remaining.add(c);
				}
			}
			ArrayList<Card> pair = cardsForPair(remaining);
			if (pair != null){
				return (pair.get(0).getValue().value() > threeKind.get(0).getValue().value())? pair.get(0).getValue() :threeKind.get(0).getValue();
			}
		}
		return null;
	}

	private static ArrayList<Card> cardsForPair(ArrayList<Card> cards) {
		for (int i = 14; i > 1; i--){
			ArrayList<Card> temp = new ArrayList<Card>();
			int numCounter = 0;
			for (Card c: cards){
				if (c.getValue() == Value.cardWithInt(i)){
					numCounter++;
					temp.add(c);
				}
			}
			if (numCounter >= 2){
				return temp;
			}
		}
		return null;
	}

	private static ArrayList<Card> cardsForThreeKind(ArrayList<Card> cards) {
		for (int i = 14; i > 1; i--){
			ArrayList<Card> temp = new ArrayList<Card>();
			int numCounter = 0;
			for (Card c: cards){
				if (c.getValue() == Value.cardWithInt(i)){
					numCounter++;
					temp.add(c);
				}
			}
			if (numCounter >= 3){
				return temp;
			}
		}
		return null;
	}

	public static Value checkForThreeOfAKind(ArrayList<Card> cards) {
		ArrayList<Card> threeKind = cardsForThreeKind(cards);
		if (threeKind != null){
			return threeKind.get(0).getValue();
		}
		return null;
	}

	public static Value checkForTwoPair(ArrayList<Card> cards) {
		ArrayList<Card> twoKind = cardsForPair(cards);
		if (twoKind != null){
			ArrayList<Card> remaining = new ArrayList<Card>();
			for (Card c: cards){
				if (!twoKind.contains(c)){
					remaining.add(c);
				}
			}
			ArrayList<Card> pair = cardsForPair(remaining);
			if (pair != null){
				return (pair.get(0).getValue().value() > twoKind.get(0).getValue().value())? pair.get(0).getValue() :twoKind.get(0).getValue();
			}
		}
		return null;
	}

	public static Value checkForPair(ArrayList<Card> cards) {
		ArrayList<Card> twoKind = cardsForPair(cards);
		if (twoKind != null){
			return twoKind.get(0).getValue();
		}
		return null;
	}
}
